# -*- indent-tabs-mode: t -*-

# based on the terrain-2 soya tutorial

import sys, os, os.path, random, soya, soya.sdlconst

soya.init()
soya.path.append(os.path.join(os.path.dirname(sys.argv[0]), "data"))

scene = soya.World()

# Creates a new terrain in the scene. terrain_size is the dimension of
# the terrain ; it must be of the form (2 ** n) + 1.

terrain_size = 257
terrain = soya.Terrain(scene, terrain_size, terrain_size)

# Sets a random value for each height.
# Other vertex-setting methods include:
#  - Terrain.set_material     (i, j, material)
#  - Terrain.set_vertex_color (i, j, color) where color is a (red, green, blue, alpha) tuple
#  - Terrain.set_vertex_option(i, j, hidden, invisible, non_solid, force_presence)


import geology
SHAPE = (terrain_size-1,terrain_size-1)
CLEVEL = 0.1
#z = geology.generate_grid(SHAPE)
z = geology.generate_pink_noise(SHAPE, 32)
z = geology.normalize(z)
#z = geology.meadowize(z, CLEVEL)
#z = geology.distort_fractally(z, degree=1.0, max_blocksize=4)
#z = geology.smooth(z)
n = (z-geology.north(z)).clip(0,999.9)
talus = n.mean() + n.std()
for i in range(10):
  z = geology.normalize(geology.thermally_erode(z, talus, 0.5, True))


for i in range(terrain_size):
  for j in range(terrain_size):
    h = z[i%SHAPE[0],j%SHAPE[1]]
    terrain.set_height(i, j, h)
    #c = 3 * int(255 * h)
    c = int(h * 255)
    terrain.set_vertex_option(i, j, force_presence=True)


# Multiplies all the heights by 4

mh = 16.0
terrain.multiply_height(mh)

# Adds a light.

light = soya.Light(scene)
light.set_xyz(0.0, 2.0 * mh, 0.0)

# Add a camera and a loop to render

class MovableCamera(soya.Camera):
  def __init__(self, parent):
    soya.Camera.__init__(self, parent)
    
    self.speed = soya.Vector(self)
    self.rotation_z_speed = 0.0
    self.rotation_y_speed = 0.0
    self.rotation_x_speed = 0.0
    
  def begin_round(self):
    soya.Camera.begin_round(self)

    for event in soya.process_event():
      if event[0] == soya.sdlconst.KEYDOWN:
        if   event[1] == soya.sdlconst.K_e:   self.speed.z = -1.0
        elif event[1] == soya.sdlconst.K_d:   self.speed.z =  1.0
        elif event[1] == soya.sdlconst.K_s:   self.speed.x = -1.0
        elif event[1] == soya.sdlconst.K_f:   self.speed.x =  1.0
        elif event[1] == soya.sdlconst.K_r:   self.speed.y = 1.0
        elif event[1] == soya.sdlconst.K_v:   self.speed.y = -1.0
        elif event[1] == soya.sdlconst.K_j:   self.rotation_y_speed = 5.0
        elif event[1] == soya.sdlconst.K_l:  self.rotation_y_speed = -5.0
        elif event[1] == soya.sdlconst.K_i:  self.rotation_x_speed = 5.0
        elif event[1] == soya.sdlconst.K_k:  self.rotation_x_speed = -5.0
        elif event[1] == soya.sdlconst.K_u:  self.rotation_z_speed = 5.0
        elif event[1] == soya.sdlconst.K_o:  self.rotation_z_speed = -5.0
        elif event[1] == soya.sdlconst.K_q:      soya.MAIN_LOOP.stop()
        elif event[1] == soya.sdlconst.K_ESCAPE: soya.MAIN_LOOP.stop()
      if event[0] == soya.sdlconst.KEYUP:
        if   event[1] == soya.sdlconst.K_e:   self.speed.z = 0.0
        elif event[1] == soya.sdlconst.K_d:   self.speed.z =  0.0
        elif event[1] == soya.sdlconst.K_s:   self.speed.x =  0.0
        elif event[1] == soya.sdlconst.K_f:   self.speed.x =  0.0
        elif event[1] == soya.sdlconst.K_r:   self.speed.y = -0.0
        elif event[1] == soya.sdlconst.K_v:   self.speed.y =  0.0
        elif event[1] == soya.sdlconst.K_j:   self.rotation_y_speed =  0.0
        elif event[1] == soya.sdlconst.K_l:  self.rotation_y_speed = -0.0
        elif event[1] == soya.sdlconst.K_i:  self.rotation_x_speed =  0.0
        elif event[1] == soya.sdlconst.K_k:  self.rotation_x_speed = -0.0
        elif event[1] == soya.sdlconst.K_u:  self.rotation_z_speed = 0.0
        elif event[1] == soya.sdlconst.K_o:  self.rotation_z_speed = -0.0

  def advance_time(self, proportion):
    self.add_mul_vector(proportion, self.speed)
    self.turn_z(self.rotation_z_speed * proportion)
    self.turn_y(self.rotation_y_speed * proportion)
    self.turn_x(self.rotation_x_speed * proportion)
      

camera = MovableCamera(scene)
camera.set_xyz(4.0 * mh, 6.0 * mh, 16.0)
camera.look_at(soya.Point(scene, terrain_size/2.0, 0.0, terrain_size/2.0))
soya.set_root_widget(camera)

soya.MainLoop(scene).main_loop()

                  
